#include <symstr.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
namespace sstd {
    extern "C" {
#endif

char *strnupr(char *_str, size_t _len) {
    char *str;
    if(_str==NULL) return NULL;
    for(str=_str; (*str=toupper(*str))!='\0' && _len; str++, --_len);
    return _str;
}
char *strlwr(char *_str, size_t _len) {
    char *str;
    if(_str==NULL) return NULL;
    for(str=_str; (*str=tolower(*str))!='\0' && _len; str++, --_len);
    return _str;
}
char *strrev(char *_str, size_t _len) {
    char *str, chr;
    size_t len;
    if(_str == NULL) return NULL;
    for(str=_str, len=0; *str!='\0' && len<_len; str++, len++);
    for(--len; str>_str; str--, _len--)
        chr = *_str, *_str = *str, *str = chr;
    return _str;
}
uint64_t strhsh_0(const char *_str) {
    uint64_t hash;
    if(_str==NULL) return HASH_ZERO;
    if(*_str=='\0') return HASH_ZERO;
    for(hash=0; *_str!='\0'; _str++)
        hash = hash*HASH_BAS0+HASH_ADD0+*_str;
    return hash;
}
void strhsh_2(const char *_str, uint64_t *_h0, uint64_t *_h1) {
    uint64_t hash0, hash1;
    if(_str==NULL || *_str=='\0'){
        hash0 = HASH_ZERO;
        hash1 = HASH_ZERO;
        goto ret;
    }
    for(hash0=hash1=0; *_str!='\0'; _str++){
        hash0 = hash0*HASH_BAS0+HASH_ADD0+*_str;
        hash1 = hash1*HASH_BAS0+HASH_ADD0+hash0;
    }
ret:
    if(_h0!=NULL) *_h0 = hash0;
    if(_h1!=NULL) *_h1 = hash1;
    return;
}
size_t *strmts(const char *_str) {
    size_t *ret = NULL;
    size_t len = strlen(_str);
    if(len==0) return NULL;
    ret = (size_t *)malloc(sizeof(size_t)*(len+1));
    if(ret==NULL) return NULL;
    ret[0] = 0;
    for(size_t i=1; i<=len; i++)
        if(_str[i] == _str[ret[i-1]])
            ret[i] = ret[i-1]+1;
        else
            ret[i] = 0;
    return ret;
}
size_t strmts_nxt(const char* _str, const char *_substr, size_t *_mts, size_t _pos) {
    size_t len = strlen(_str), len_sub = strlen(_substr);
    size_t i, j;
    if(len==0 || len_sub==0 || _mts==NULL) return -1;
    if(_pos>=len || _pos+len_sub>=len) return -1;
    for(i=_pos, j=0; i<len && j<len_sub; i++){
        if(_str[i] == _substr[j])
            j++;
        else j = _mts[j];
    }
    if(j==len_sub) return i-len_sub;
    return -1;
}

#ifdef __cplusplus
    }
}
#endif
